#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
高级自动打包脚本
支持多种镜像源和打包选项
"""

import os
import sys
import subprocess
import tkinter as tk
from tkinter import messagebox

# 可用的镜像源
MIRRORS = {
    "1": {
        "name": "清华大学",
        "url": "https://pypi.tuna.tsinghua.edu.cn/simple/"
    },
    "2": {
        "name": "阿里云",
        "url": "https://mirrors.aliyun.com/pypi/simple/"
    },
    "3": {
        "name": "中科大",
        "url": "https://pypi.mirrors.ustc.edu.cn/simple/"
    },
    "4": {
        "name": "豆瓣",
        "url": "https://pypi.douban.com/simple/"
    },
    "5": {
        "name": "官方源（较慢）",
        "url": "https://pypi.org/simple/"
    }
}

def select_mirror():
    """选择镜像源"""
    print("\n请选择PyPI镜像源：")
    for key, mirror in MIRRORS.items():
        print(f"{key}. {mirror['name']} - {mirror['url']}")
    
    while True:
        choice = input("\n请输入选择（1-5，默认1）: ").strip() or "1"
        if choice in MIRRORS:
            selected = MIRRORS[choice]
            print(f"✓ 已选择：{selected['name']}")
            return selected['url']
        print("❌ 无效选择，请重新输入")

def check_pyinstaller(mirror_url):
    """检查PyInstaller是否已安装"""
    try:
        import PyInstaller
        print("✓ PyInstaller 已安装")
        return True
    except ImportError:
        print("❌ PyInstaller 未安装")
        return install_pyinstaller(mirror_url)

def install_pyinstaller(mirror_url):
    """安装PyInstaller"""
    print("正在安装 PyInstaller...")
    try:
        subprocess.check_call([sys.executable, "-m", "pip", "install", "pyinstaller", 
                              "-i", mirror_url])
        print("✓ PyInstaller 安装成功")
        return True
    except subprocess.CalledProcessError:
        print("❌ PyInstaller 安装失败")
        return False

def install_requirements(mirror_url):
    """安装项目依赖"""
    if os.path.exists("requirements.txt"):
        print("正在安装项目依赖...")
        try:
            subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", 
                                  "requirements.txt", "-i", mirror_url])
            print("✓ 依赖安装成功")
            return True
        except subprocess.CalledProcessError:
            print("❌ 依赖安装失败")
            return False
    else:
        print("⚠️  未找到 requirements.txt 文件")
        return True

def select_build_option():
    """选择打包选项"""
    print("\n请选择打包方式：")
    print("1. 单文件模式（--onefile）- 生成单个exe文件（推荐）")
    print("2. 目录模式（--onedir）- 生成包含依赖的文件夹（启动较快）")
    
    while True:
        choice = input("\n请输入选择（1-2，默认1）: ").strip() or "1"
        if choice == "1":
            return "--onefile"
        elif choice == "2":
            return "--onedir"
        print("❌ 无效选择，请重新输入")

def build_exe(build_mode):
    """构建exe文件"""
    print("开始打包程序...")
    
    # 基础PyInstaller命令参数
    cmd = [
        "pyinstaller",
        build_mode,                     # --onefile 或 --onedir
        "--windowed",                   # 隐藏控制台窗口  
        "--name=英语单词训练系统",         # 设置exe文件名
        "--add-data=cet-4_json;cet-4_json",  # 包含数据文件夹
        "--hidden-import=matplotlib.backends.backend_tkagg",
        "--hidden-import=PIL._tkinter_finder",
        "--distpath=.",                 # 输出到当前目录
        "--workpath=build",
        "--clean",                      # 清理之前的构建文件
        "main.py"                       # 主程序文件
    ]
    
    # 可选参数
    if os.path.exists("icon.ico"):
        cmd.insert(-1, "--icon=icon.ico")
        print("✓ 找到图标文件，将添加到exe中")
    
    if os.path.exists("training_data"):
        cmd.insert(-1, "--add-data=training_data;training_data")
        print("✓ 找到训练数据文件夹，将包含在打包中")
    
    try:
        print(f"执行命令: {' '.join(cmd)}")
        subprocess.check_call(cmd)
        print(f"\n🎉 打包成功！")
        print(f"exe文件位置: 英语单词训练系统.exe (项目根目录)")
        print("💡 重要提示：exe文件已放置在项目根目录，可以直接访问所有数据文件")
        
        if build_mode == "--onefile":
            print("exe文件位置: dist/英语单词训练系统.exe")
        else:
            print("程序文件夹位置: dist/英语单词训练系统/")
        
        return True
        
    except subprocess.CalledProcessError as e:
        print(f"❌ 打包失败: {e}")
        return False

def main():
    print("=" * 60)
    print("     英语单词训练系统 - 高级打包工具")
    print("=" * 60)
    
    # 检查当前目录
    if not os.path.exists("main.py"):
        print("❌ 错误：请在项目根目录运行此脚本")
        input("按回车键退出...")
        return
    
    if not os.path.exists("cet-4_json"):
        print("❌ 错误：未找到 cet-4_json 文件夹")
        input("按回车键退出...")
        return
    
    # 选择镜像源
    mirror_url = select_mirror()
    
    # 安装依赖
    if not install_requirements(mirror_url):
        input("按回车键退出...")
        return
    
    # 检查并安装PyInstaller
    if not check_pyinstaller(mirror_url):
        input("按回车键退出...")
        return
    
    # 选择打包模式
    build_mode = select_build_option()
    
    # 开始打包
    if build_exe(build_mode):
        print("\n📋 使用说明：")
        if build_mode == "--onefile":
            print("1. exe文件已生成在 dist 文件夹中")
            print("2. 可直接运行，第一次启动较慢")
            print("3. 分发时只需要exe文件")
        else:
            print("1. 程序文件夹已生成在 dist 文件夹中")
            print("2. 启动速度较快")
            print("3. 分发时需要整个文件夹")
        print("4. 用户无需安装Python即可使用")
        
        # 询问是否测试运行
        if input("\n是否现在测试运行打包的程序？(y/N): ").lower() == 'y':
            test_exe(build_mode)
    
    input("\n按回车键退出...")

def test_exe(build_mode):
    """测试生成的exe文件"""
    exe_path = "英语单词训练系统.exe"
    
    if os.path.exists(exe_path):
        print(f"✓ 找到exe文件: {exe_path}")
        if messagebox.askyesno("测试运行", "是否要测试运行生成的exe文件？"):
            try:
                subprocess.Popen([exe_path])
                print("✓ exe文件启动成功")
            except Exception as e:
                print(f"❌ exe文件启动失败: {e}")
    else:
        print(f"❌ 未找到exe文件: {exe_path}")

if __name__ == "__main__":
    main() 